package pl.cba.solgar.game.rogal.map;

import java.util.Random;
import java.util.Vector;

import org.newdawn.slick.Color;
import org.newdawn.slick.Image;

import pl.cba.solgar.game.rogal.Room;
import pl.cba.solgar.game.rogal.console.Console;
import pl.cba.solgar.game.rogal.map.tiles.AbstractTile;

public class Map
{

    private final int mapWidth;
    private final int mapHeight;
    private MapTile[][] mapData;
    Vector<Image> images = new Vector<Image>();
    Random random = new Random(System.currentTimeMillis());
    public static Vector<Room> _rooms = new Vector<Room>();
    public static java.util.HashMap<String, AbstractTile> tileDefinitions;

    private long animTimer;

    static
    {
        tileDefinitions = new java.util.HashMap<String, AbstractTile>();
        tileDefinitions.put(AbstractTile.TILE_CAVE_WALL,     new AbstractTile(AbstractTile.TILE_CAVE_WALL));
        tileDefinitions.put(AbstractTile.TILE_CAVE_FLOOR,    new AbstractTile(AbstractTile.TILE_CAVE_FLOOR));
        tileDefinitions.put(AbstractTile.TILE_OUTDOOR_GRASS, new AbstractTile(AbstractTile.TILE_OUTDOOR_GRASS));
    }

    public Map(int width, int height)
    {
    	animTimer = System.currentTimeMillis();

        mapWidth = width;
        mapHeight = height;

        mapData = new MapTile[width][height];
        /// generate

        for (int y = 0; y < mapData[0].length; ++y)
        {
            for (int x = 0; x < mapData.length; ++x)
            {
                mapData[x][y] = new MapTile(null);
                mapData[x][y].tile = (AbstractTile) tileDefinitions.values().toArray()[random.nextInt(tileDefinitions.size())];
            }
        }
    }

    public void resetVisited()
    {
    	 for (int y = 0; y < mapData[0].length; ++y)
             for (int x = 0; x < mapData.length; ++x)
             {
                 mapData[x][y].visited = false;
                 mapData[x][y].moveCost = -1;
             }
    }

    public void generateLevel(int rooms, int minSize, int maxSize)
    {
        _rooms.removeAllElements();
        for (int y = 0; y < mapData[0].length; ++y)
        {
            for (int x = 0; x < mapData.length; ++x)
            {
                mapData[x][y].tile = tileDefinitions.get("cave_wall");
            }
        }

        int generation = 0;

        for (int room = 1; room <= rooms; ++room, ++generation)
        {
            if (generation == 200)
            {
                System.out.println("generation escape");
                break;
            }

            int w = 0;
            int h = 0;
            int x = 0;
            int y = 0;

            do
            {
                w = random.nextInt(mapWidth - 1);
                h = random.nextInt(mapHeight - 1);
            }
            while (w * h < minSize || w * h > maxSize || w < 5 || h < 4 || w > 15 || h > 7);

            x = random.nextInt(mapWidth - w);
            y = random.nextInt(mapHeight - h);

            boolean generationFailed = false;

            for (int py = -1; py < h + 1; ++py)
            {
                for (int px = -1; px < w + 1; ++px)
                {
                    int cellX = x + px;
                    int cellY = y + py;
                    if (cellX < 0 || cellY < 0
                            || cellX >= mapWidth || cellY >= mapHeight
                            || (mapData[cellX][cellY].tile.getTypeName().compareTo("cave_floor") == 0))
                    {
                        generationFailed = true;
                        break;
                    }
                    if (generationFailed)
                    {
                        break;
                    }
                }
            }

            if (generationFailed)
            {
                room -= 1;
                continue;
            }

            _rooms.add(new Room(x, y, w, h));

            for (int py = 0; py < h; ++py)
            {
                for (int px = 0; px < w; ++px)
                {
                    mapData[x + px][y + py].tile = tileDefinitions.get("cave_floor");
                }
            }
        }
    }

    public void render(Console c)
    {
    	boolean nextFrame = false;
    	if (System.currentTimeMillis() - animTimer >= 10)
        {
    		nextFrame = true;
        	animTimer = System.currentTimeMillis();
        }
        for (int y = 0; y < mapData[0].length; ++y)
        {
            for (int x = 0; x < mapData.length; ++x)
            {
            	Color bg = mapData[x][y].background == null ? mapData[x][y].tile.getBackbroundColor() :
            												  mapData[x][y].background ;
                c.setChar(mapData[x][y].tile.getChar(), x, y, mapData[x][y].tile.getColor(), bg);
                if (nextFrame)
                	mapData[x][y].tile.nextFrame();
            }
        }
    }

    public MapTile[][] getMapData()
    {
        return mapData;
    }
}
